home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / boot / netBoot.new / sys / inet.c < prev    next >
C/C++ Source or Header  |  1990-12-19  |  9KB  |  344 lines

  1.  
  2. /*
  3.  * @(#)inet.c 1.1 86/09/27
  4.  * Copyright (c) 1986 by Sun Microsystems, Inc.
  5.  */
  6.  
  7. /*
  8.  * Standalone IP send and receive - specific to Ethernet
  9.  * Includes ARP and Reverse ARP
  10.  */
  11. #include "../dev/saio.h"
  12. #include "../h/socket.h"
  13. #include "../dev/if.h"
  14. #include "../h/in.h"
  15. #include "../dev/if_ether.h"
  16. #include "../h/in_systm.h"
  17. #include "../h/ip.h"
  18. #include "../h/sainet.h"
  19. #include "../h/sunromvec.h"
  20. #include "../h/idprom.h"
  21.  
  22. #define millitime() (*romp->v_nmiclock)
  23.  
  24. struct ether_addr etherbroadcastaddr = { 
  25.     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  26. };
  27.  
  28. struct arp_packet {
  29.     struct ether_header    arp_eh;
  30.     struct ether_arp    arp_ea;
  31. #define    used_size (sizeof (struct ether_header)+sizeof(struct ether_arp))
  32.     char    filler[ETHERMIN - sizeof(struct ether_arp)];
  33. };
  34.  
  35. #define WAITCNT    2    /* 4 seconds before bitching about arp/revarp */
  36.  
  37. /*
  38.  * Fetch our Ethernet address from the ID prom
  39.  */
  40. myetheraddr(ea)
  41.     struct ether_addr *ea;
  42. {
  43.     struct idprom id;
  44.  
  45.     if (idprom(IDFORM_1, &id) != IDFORM_1) {
  46.         printf("ERROR: missing or invalid ID prom\n");
  47.         return;
  48.     }
  49.     *ea = *(struct ether_addr *)id.id_ether;
  50. }
  51.  
  52. /*
  53.  * Initialize IP state
  54.  * Find out our Ethernet address and call Reverse ARP
  55.  * to find out our Internet address
  56.  * Set the ARP cache to the broadcast host
  57.  */
  58. inet_init(sip, sain, tmpbuf)
  59.     register struct saioreq *sip;
  60.     register struct sainet *sain;
  61.     char *tmpbuf;
  62. {
  63.     myetheraddr(&sain->sain_myether);
  64.     sain->sain_hisaddr.s_addr = 0;
  65.     sain->sain_hisether = etherbroadcastaddr;
  66.     revarp(sip, sain, tmpbuf);
  67. }
  68.  
  69.  
  70. /*
  71.  * Output an IP packet
  72.  * Cause ARP to be invoked if necessary
  73.  */
  74. ip_output(sip, buf, len, sain, tmpbuf)
  75.     register struct saioreq *sip;
  76.     caddr_t buf, tmpbuf;
  77.     short len;
  78.     register struct sainet *sain;
  79. {
  80.     register struct ether_header *eh;
  81.     register struct ip *ip;
  82.  
  83.     eh = (struct ether_header *)buf;
  84.     ip = (struct ip *)(buf + sizeof(struct ether_header));
  85.     if (ip->ip_dst.s_addr != sain->sain_hisaddr.s_addr) {
  86.         sain->sain_hisaddr.s_addr = ip->ip_dst.s_addr;
  87.         arp(sip, sain, tmpbuf);
  88.     }
  89.     eh->ether_type = ETHERPUP_IPTYPE;
  90.     eh->ether_shost = sain->sain_myether;
  91.     eh->ether_dhost = sain->sain_hisether;
  92.     /* checksum the packet */
  93.     ip->ip_sum = 0;
  94.     ip->ip_sum = ipcksum((caddr_t)ip, sizeof (struct ip));
  95.     if (len < ETHERMIN+sizeof(struct ether_header))
  96.         len = ETHERMIN+sizeof(struct ether_header);
  97.     return (*sip->si_sif->sif_xmit)(sip->si_devdata, buf, len);
  98. }
  99.  
  100. /*
  101.  * Check incoming packets for IP packets
  102.  * addressed to us. Also, respond to ARP packets
  103.  * that wish to know about us.
  104.  * Returns a length for any IP packet addressed to us, 0 otherwise.
  105.  */
  106. ip_input(sip, buf, sain)
  107.     register struct saioreq *sip;
  108.     caddr_t buf;
  109.     register struct sainet *sain;
  110. {
  111.     register short len;
  112.     register struct ether_header *eh;
  113.     register struct ip *ip;
  114.     register struct ether_arp *ea;
  115.  
  116.     len = (*sip->si_sif->sif_poll)(sip->si_devdata, buf);
  117.     eh = (struct ether_header *)buf;
  118.     if (eh->ether_type == ETHERPUP_IPTYPE &&
  119.         len >= sizeof(struct ether_header)+sizeof(struct ip)) {
  120.         ip = (struct ip *)(buf + sizeof(struct ether_header));
  121.         if (ip->ip_dst.s_addr != sain->sain_myaddr.s_addr) 
  122.             return (0);
  123.         return (len);
  124.     }
  125.     if (eh->ether_type == ETHERPUP_ARPTYPE &&
  126.         len >= sizeof(struct ether_header)+sizeof(struct ether_arp)) {
  127.         ea = (struct ether_arp *)(buf + sizeof(struct ether_header));
  128.         if (ea->arp_pro != ETHERPUP_IPTYPE) 
  129.             return (0);
  130.         if (arp_spa(ea).s_addr == sain->sain_hisaddr.s_addr)
  131.             sain->sain_hisether = arp_sha(ea);
  132.         if (ea->arp_op == ARPOP_REQUEST &&
  133.             arp_tpa(ea).s_addr == sain->sain_myaddr.s_addr) {
  134.             ea->arp_op = ARPOP_REPLY;
  135.             eh->ether_dhost = arp_sha(ea);
  136.             eh->ether_shost = sain->sain_myether;
  137.             arp_tha(ea) = arp_sha(ea);
  138.             arp_tpa(ea) = arp_spa(ea);
  139.             arp_sha(ea) = sain->sain_myether;
  140.             arp_spa(ea) = sain->sain_myaddr;
  141.             (*sip->si_sif->sif_xmit)(sip->si_devdata, buf, 
  142.                         sizeof(struct arp_packet));
  143.         }
  144.         return (0);
  145.     }
  146.     return (0);
  147. }
  148.  
  149. /*
  150.  * arp
  151.  * Broadcasts to determine Ethernet address given IP address
  152.  * See RFC 826
  153.  */
  154. arp(sip, sain, tmpbuf)
  155.     register struct saioreq *sip;
  156.     register struct sainet *sain;
  157.     char *tmpbuf;
  158. {
  159.     struct arp_packet out;
  160.  
  161.     if (in_lnaof(sain->sain_hisaddr) == INADDR_ANY ||
  162.         (in_lnaof(sain->sain_hisaddr) & INADDR1_ANY) == INADDR1_ANY) {
  163.         sain->sain_hisether = etherbroadcastaddr;
  164.         return;
  165.     }
  166.     out.arp_eh.ether_type = ETHERPUP_ARPTYPE;
  167.     out.arp_ea.arp_op = ARPOP_REQUEST;
  168.     arp_tha(&out.arp_ea) = etherbroadcastaddr;    /* what we want */
  169.     arp_tpa(&out.arp_ea).s_addr = sain->sain_hisaddr.s_addr;
  170.     comarp(sip, sain, &out, tmpbuf);
  171. }
  172.  
  173. /*
  174.  * Reverse ARP client side
  175.  * Determine our Internet address given our Ethernet address
  176.  * See RFC 903
  177.  */
  178. revarp(sip, sain, tmpbuf)
  179.     register struct saioreq *sip;
  180.     register struct sainet *sain;
  181.     char *tmpbuf;
  182. {
  183.     struct arp_packet out;
  184.  
  185.     out.arp_eh.ether_type = ETHERPUP_REVARPTYPE;
  186.     out.arp_ea.arp_op = REVARP_REQUEST;
  187.     arp_tha(&out.arp_ea) = sain->sain_myether;
  188.     arp_tpa(&out.arp_ea).s_addr = 0;    /* what we want to find out */
  189.     comarp(sip, sain, &out, tmpbuf);
  190. }
  191.  
  192. /*
  193.  * Common ARP code 
  194.  * Broadcast the packet and wait for the right response.
  195.  * Fills in *sain with the results
  196.  */
  197. comarp(sip, sain, out, tmpbuf)
  198.     register struct saioreq *sip;
  199.     register struct sainet *sain;
  200.     register struct arp_packet *out;
  201.     char *tmpbuf;
  202. {
  203.     register struct arp_packet *in = (struct arp_packet *)tmpbuf;
  204.     register int e, count, time, feedback,len, delay = 2;
  205.     char    *ind = "-\\|/";
  206.  
  207.     out->arp_eh.ether_dhost = etherbroadcastaddr;
  208.     out->arp_eh.ether_shost = sain->sain_myether;
  209.     out->arp_ea.arp_hrd =  ARPHRD_ETHER;
  210.     out->arp_ea.arp_pro = ETHERPUP_IPTYPE;
  211.     out->arp_ea.arp_hln = sizeof(struct ether_addr);
  212.     out->arp_ea.arp_pln = sizeof(struct in_addr);
  213.     arp_sha(&out->arp_ea) = sain->sain_myether;
  214.     arp_spa(&out->arp_ea).s_addr = sain->sain_myaddr.s_addr;
  215.     feedback = 0;
  216.  
  217.     for (count=0; ; count++) {
  218.         if (count == WAITCNT) {
  219.             if (out->arp_ea.arp_op == ARPOP_REQUEST) {
  220.                 printf("Requesting Ethernet address for ");
  221.                 inet_print(arp_tpa(&out->arp_ea));
  222.             } else {
  223.                 printf("Requesting Internet address for ");
  224.                 ether_print(&arp_tha(&out->arp_ea));
  225.             }
  226.         }
  227.         e = (*sip->si_sif->sif_xmit)(sip->si_devdata, (caddr_t)out,
  228.             sizeof *out);
  229.         
  230.         time = millitime() + (delay * 1000);    /* broadcast delay */
  231.         printf("%c\b", ind[feedback++ % 4]);    /* Show activity */
  232.  
  233.         while (millitime() <= time) {
  234.             len = (*sip->si_sif->sif_poll)(sip->si_devdata, tmpbuf);
  235.             if (len < used_size)
  236.                 continue;
  237.             if (in->arp_ea.arp_pro != ETHERPUP_IPTYPE)
  238.                 continue;
  239.             if (out->arp_ea.arp_op == ARPOP_REQUEST) {
  240.                 if (in->arp_eh.ether_type != ETHERPUP_ARPTYPE)
  241.                     continue;
  242.                 if (in->arp_ea.arp_op != ARPOP_REPLY)
  243.                     continue;
  244.                 if (arp_spa(&in->arp_ea).s_addr !=
  245.                     arp_tpa(&out->arp_ea).s_addr)
  246.                     continue;
  247.                 if (count >= WAITCNT) {
  248.                     printf("Found at ");
  249.                     ether_print(&arp_sha(&in->arp_ea));
  250.                 }
  251.                 sain->sain_hisether = arp_sha(&in->arp_ea);
  252.                 return;
  253.             } else {        /* Reverse ARP */
  254.                 if (in->arp_eh.ether_type !=ETHERPUP_REVARPTYPE)
  255.                     continue;
  256.                 if (in->arp_ea.arp_op != REVARP_REPLY)
  257.                     continue;
  258.                 if (bcmp((caddr_t)&arp_tha(&in->arp_ea),
  259.                     (caddr_t)&arp_tha(&out->arp_ea), 
  260.                     sizeof (struct ether_addr)) != 0)
  261.                     continue;
  262.  
  263.                 printf("Using IP Address ");
  264.                 inet_print(arp_tpa(&in->arp_ea));
  265.  
  266.                 sain->sain_myaddr = arp_tpa(&in->arp_ea);
  267.                 /* short circuit first ARP */
  268.                 sain->sain_hisaddr = arp_spa(&in->arp_ea);
  269.                 sain->sain_hisether = arp_sha(&in->arp_ea);
  270.                 return;
  271.             }
  272.         }
  273.         delay = delay * 2;    /* Double the request delay */
  274.  
  275.         if (delay > 64)        /* maximum delay is 64 seconds */
  276.             delay = 64;
  277.  
  278.         (*sip->si_sif->sif_reset)(sip->si_devdata);
  279.     }
  280.     /* NOTREACHED */
  281. }
  282.  
  283. /*
  284.  * Return the host portion of an internet address.
  285.  */
  286. in_lnaof(in)
  287.     struct in_addr in;
  288. {
  289.     register u_long i = ntohl(in.s_addr);
  290.  
  291.     if (IN_CLASSA(i))
  292.         return ((i)&IN_CLASSA_HOST);
  293.     else if (IN_CLASSB(i))
  294.         return ((i)&IN_CLASSB_HOST);
  295.     else
  296.         return ((i)&IN_CLASSC_HOST);
  297. }
  298.  
  299. /*
  300.  * Compute one's complement checksum
  301.  * for IP packet headers 
  302.  */
  303. ipcksum(cp, count)
  304.     caddr_t    cp;
  305.     register unsigned short    count;
  306. {
  307.     register unsigned short    *sp = (unsigned short *)cp;
  308.     register unsigned long    sum = 0;
  309.     register unsigned long    oneword = 0x00010000;
  310.  
  311.     count >>= 1;
  312.     while (count--) {
  313.         sum += *sp++;
  314.         if (sum >= oneword) {        /* Wrap carries into low bit */
  315.             sum -= oneword;
  316.             sum++;
  317.         }
  318.     }
  319.     return (~sum);
  320. }
  321.  
  322. inet_print(s)
  323.     struct in_addr s;
  324. {
  325.     int    len = 2;
  326.  
  327.     printf("%d.%d.%d.%d = ", s.S_un.S_un_b.s_b1, s.S_un.S_un_b.s_b2,
  328.         s.S_un.S_un_b.s_b3, s.S_un.S_un_b.s_b4);
  329.  
  330.     printhex(s.S_un.S_un_b.s_b1, len);
  331.     printhex(s.S_un.S_un_b.s_b2, len);
  332.     printhex(s.S_un.S_un_b.s_b3, len);
  333.     printhex(s.S_un.S_un_b.s_b4, len);
  334.     printf("\n");
  335. }
  336.  
  337. ether_print(ea)
  338.     struct ether_addr *ea;
  339. {
  340.     register u_char *p = &ea->ether_addr_octet[0];
  341.  
  342.     printf("%x:%x:%x:%x:%x:%x\n", p[0], p[1], p[2], p[3], p[4], p[5]);
  343. }
  344.